package Controller

import (
	"back_go/DAO/gorm"
	"back_go/DAO/gorm/GormModel"
	"back_go/Dto"
	"back_go/Response"
	"back_go/Util"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/copier"
	"log"
	"math"
	"strconv"
	"time"
)

type ProductParam struct {
	ProdId             *int64            `form:"prodId"`
	Status             *int              `form:"status"`
	ProdName           string            `form:"prodName"`
	Price              *float64          `form:"price"`
	OriPrice           *float64          `form:"oriPrice"`
	TotalStocks        *int              `form:"totalStocks"`
	Brief              string            `form:"brief"`
	Pic                string            `form:"pic"`
	Imgs               string            `form:"imgs"`
	CategoryId         *int64            `form:"categoryId"`
	SkuList            []GormModel.TzSku `form:"skuList"`
	Content            string            `form:"content"`
	DeliveryModeVo     *Dto.DeliveryMode `form:"deliveryModeVo"`
	DeliveryTemplateId *int64            `form:"deliveryTemplateId"`
	TagList            []int64           `form:"tagList"`
}

func GetProdByPage(c *gin.Context) {

	// 解析分页参数
	currentStr := c.Query("current")
	sizeStr := c.Query("size")
	statusStr := c.Query("status")

	// 将字符串类型的分页参数转换为整数
	current, err := strconv.Atoi(currentStr)
	if err != nil {
		current = 1 // 默认当前页为 1
	}
	size, err := strconv.Atoi(sizeStr)
	if err != nil {
		size = 10 // 默认每页显示 10 条记录
	}

	// 解析状态参数
	var status *int
	if statusStr != "" {
		statusInt, err := strconv.Atoi(statusStr)
		if err == nil {
			status = &statusInt
		}
	}

	// 绑定查询参数到 ProductParam 结构体
	var product ProductParam
	if err := c.ShouldBindQuery(&product); err != nil {

	}

	// 如果状态参数在 URL 中单独传递，覆盖结构体中的状态值
	if status != nil {
		product.Status = status
	}
	db := gorm.Db
	// 构建查询
	query := db.Model(&GormModel.TzProd{})

	// 根据 ProductParam 中的字段动态构建查询条件
	if product.ProdId != nil {
		query = query.Where("prod_id = ?", *product.ProdId)
	}
	if product.Status != nil {
		query = query.Where("status = ?", *product.Status)
	}
	if product.ProdName != "" {
		query = query.Where("prod_name LIKE ?", "%"+product.ProdName+"%")
	}
	if product.Price != nil {
		query = query.Where("price = ?", *product.Price)
	}
	if product.OriPrice != nil {
		query = query.Where("ori_price = ?", *product.OriPrice)
	}
	if product.TotalStocks != nil {
		query = query.Where("total_stocks = ?", *product.TotalStocks)
	}
	if product.CategoryId != nil {
		query = query.Where("category_id = ?", *product.CategoryId)
	}
	if product.DeliveryTemplateId != nil {
		query = query.Where("delivery_template_id = ?", *product.DeliveryTemplateId)
	}

	// 计算偏移量
	offset := (current - 1) * size

	// 执行分页查询
	var products []GormModel.TzProd
	var total int64
	if err := query.Count(&total).Error; err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:      "A00005",
			Data:      nil,
			Msg:       "服务器出了问题",
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Fail:      true,
			Success:   false,
		})
		return
	}
	if err := query.Offset(offset).Limit(size).Find(&products).Error; err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:      "A00005",
			Data:      nil,
			Msg:       "服务器出了问题",
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Fail:      true,
			Success:   false,
		})
		return
	}

	// 返回分页结果
	c.JSON(200, Response.ResponseBody{
		Code: "00000",
		Data: PageParam1[GormModel.TzPickAddr]{
			Current: current,
			Total:   total,
			Size:    size,
			Records: products,
			Pages:   int(math.Ceil(float64(total) / float64(size))),
		},
		Msg:       nil,
		Success:   true,
		Fail:      false,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Sign:      "",
	})
}

func GetProdByProdId(c *gin.Context) {
	prodId := c.Param("prodId")
	db := gorm.Db
	var prod GormModel.TzProd
	db.Model(&GormModel.TzProd{}).Where("prod_id =?", prodId).First(&prod)
	//一个商店不需要鉴定
	var skuList []GormModel.TzSku
	//select * from tz_sku where prod_id = #{prodId} and is_delete = 0
	db.Model(&GormModel.TzSku{}).Where("prod_id =?", prodId).Where("is_delete = 0").Find(&skuList)
	prod.SkuList = skuList
	//获取分组标签
	var listTagId []int64
	//SELECT tag_id FROM tz_prod_tag_reference WHERE prod_id = #{prodId}
	db.Model(&GormModel.TzProdTagReference{}).Where("prod_id =?", prodId).Pluck("tag_id", &listTagId)
	prod.TagList = listTagId
	c.JSON(200, Response.ResponseBody{
		Code:      "00000",
		Data:      prod,
		Msg:       nil,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Sign:      "",
		Success:   true,
	})
}

func checkParam(productParam ProductParam) (bool, error) {
	if Util.SliceIsEmpty(productParam.TagList) {
		return false, fmt.Errorf("请选择产品分组")
	}
	var deliveryMode *Dto.DeliveryMode = productParam.DeliveryModeVo
	var hasDeliverMode bool = deliveryMode != nil && (deliveryMode.HasShopDelivery || deliveryMode.HasUserPickUp)
	if !hasDeliverMode {
		return false, fmt.Errorf("请选择配送方式")
	}
	var skuList []GormModel.TzSku = productParam.SkuList

	var isAllUnUse bool = true
	for _, sku := range skuList {
		if *sku.Status == 1 {
			isAllUnUse = false
		}
	}
	if isAllUnUse {
		return false, fmt.Errorf("至少要启用一种商品规格")
	}
	return true, nil
}

func UpdateProd(c *gin.Context) {
	var productParam ProductParam
	err := c.ShouldBindJSON(&productParam)
	_, err = checkParam(productParam)
	if err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:      "A00005",
			Data:      nil,
			Msg:       err.Error(),
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		return
	}
	db := gorm.Db.Begin()
	// 开启事务 defer 回滚
	defer func() {
		if r := recover(); r != nil {
			db.Rollback()
			c.JSON(200, Response.ResponseBody{
				Code:    "A00005",
				Data:    nil,
				Success: true,
				Msg:     "服务器出了点小差",
			})
		} else if err != nil {
			db.Rollback()
		} else {
			db.Commit()
		}
	}()
	var dbProduct GormModel.TzProd
	db.Model(&GormModel.TzProd{}).Where("prod_id =?", productParam.ProdId).First(&dbProduct)
	//只有一家商店，不需要鉴权
	var dbSkus []GormModel.TzSku
	db.Model(&GormModel.TzSku{}).Where("prod_id =?", dbProduct.ProdID).Find(&dbSkus)
	var product GormModel.TzProd
	err = copier.CopyWithOption(&product, &productParam, copier.Option{IgnoreEmpty: true, DeepCopy: true})

	// 将 DeliveryMode 转换为 JSON 字符串
	jsonData, err := json.Marshal(productParam.DeliveryModeVo)
	if err != nil {
		fmt.Println("Error marshaling DeliveryMode:", err)
		return
	}

	// 将 JSON 字符串存储到 SqlNullString 中
	var nullStr GormModel.SqlNullString
	nullStr.String = string(jsonData)
	nullStr.Valid = true

	// 直接将 nullStr 赋值给 product.DeliveryMode
	product.DeliveryMode = nullStr
	time := time.Now()
	product.UpdateTime = &time
	product.ShopID = dbProduct.ShopID
	if (dbProduct.Status != nil && *dbProduct.Status == 0) || (productParam.Status != nil && *productParam.Status == 1) {
		product.PutawayTime = &time
	}
	dbProduct.SkuList = dbSkus
	//-------------------------------------
	updateProduct(product, dbProduct)
	//---------------------------------------
	c.JSON(200, Response.ResponseBody{
		Code:      "00000",
		Data:      nil,
		Msg:       nil,
		Version:   "1.0",
		Timestamp: time.Unix(),
		Sign:      "",
		Success:   true,
	})
}

func SaveProd(c *gin.Context) {
	var productParam ProductParam
	err := c.ShouldBindJSON(&productParam)
	_, err = checkParam(productParam)
	if err != nil {
		c.JSON(200, Response.ResponseBody{
			Code:      "A00005",
			Data:      nil,
			Msg:       err.Error(),
			Version:   "1.0",
			Timestamp: time.Now().Unix(),
			Sign:      "",
			Success:   true,
		})
		return
	}
	var product GormModel.TzProd
	err = copier.CopyWithOption(&product, &productParam, copier.Option{IgnoreEmpty: true, DeepCopy: true})
	// 将 DeliveryMode 转换为 JSON 字符串
	jsonData, err := json.Marshal(productParam.DeliveryModeVo)
	if err != nil {
		fmt.Println("Error marshaling DeliveryMode:", err)
		return
	}
	// 将 JSON 字符串存储到 SqlNullString 中
	var nullStr GormModel.SqlNullString
	nullStr.String = string(jsonData)
	nullStr.Valid = true
	// 直接将 nullStr 赋值给 product.DeliveryMode
	product.DeliveryMode = nullStr
	tmpTime := time.Now()
	product.CreateTime = &tmpTime
	product.UpdateTime = &tmpTime
	if product.Status != nil && *product.Status == 1 {
		product.PutawayTime = &tmpTime
	}
	db := gorm.Db.Begin()

	db.Save(&product)

	// 开启事务 defer 回滚
	defer func() {
		if r := recover(); r != nil {
			db.Rollback()
			c.JSON(200, Response.ResponseBody{
				Code:    "A00005",
				Data:    nil,
				Success: true,
				Msg:     "服务器出了点小差",
			})
		} else if err != nil {
			db.Rollback()
		} else {
			db.Commit()
		}
	}()
	if Util.SliceIsNotEmpty(product.SkuList) {
		//skuMapper.insertBatch(product.getProdId(), product.getSkuList());
		for i := range product.SkuList {
			product.SkuList[i].ProdID = product.ProdID
		}
		db.Save(&product.SkuList)
	}
	//   prodTagReferenceMapper.insertBatch(product.getShopId(), product.getProdId(), product.getTagList());
	// 准备批量插入的数据
	var insertList []GormModel.TzProdTagReference
	//手动将商店id设置为1
	for _, tag := range product.TagList {
		insertList = append(insertList, GormModel.TzProdTagReference{
			ShopID:     1,
			ProdID:     int64(*product.ProdID),
			TagID:      tag,
			CreateTime: time.Now(),
		})
	}

	// 执行批量插入操作
	db.Create(&insertList)

	c.JSON(200, Response.ResponseBody{
		Code:      "00000",
		Data:      nil,
		Msg:       nil,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Sign:      "",
		Success:   true,
	})
}
func DeleteProd(c *gin.Context) {
	db := gorm.Db.Begin()
	var prodIdsList []int64

	// 从请求参数中获取id列表
	err := c.ShouldBindJSON(&prodIdsList)

	log.Println(prodIdsList)
	defer func() {
		if r := recover(); r != nil {
			db.Rollback()
			c.JSON(200, Response.ResponseBody{
				Code:    "A00005",
				Data:    nil,
				Success: true,
				Msg:     "服务器出了点小差",
			})
		} else if err != nil {
			db.Rollback()
		} else {
			db.Commit()
		}
	}()
	for _, prodId := range prodIdsList {
		log.Println("删除产品id", prodId)
		_ = deleteProduct(prodId)

	}
	c.JSON(200, Response.ResponseBody{
		Code:      "00000",
		Data:      nil,
		Msg:       nil,
		Version:   "1.0",
		Timestamp: time.Now().Unix(),
		Sign:      "",
		Success:   true,
	})
}

func deleteProduct(prodId int64) error {
	db := gorm.Db.Begin()

	var dbProduct GormModel.TzProd
	err := db.Model(&GormModel.TzProd{}).Where("prod_id =?", prodId).First(&dbProduct).Error
	db.Delete(&GormModel.TzProd{}, prodId)
	defer func() {
		if r := recover(); r != nil || err != nil {
			log.Println("删除产品id事务回滚", err)
			db.Rollback()
		} else {
			log.Println("删除产品id事务提交")
			db.Commit()
		}
	}()

	return nil
}
func updateProduct(product GormModel.TzProd, dbProduct GormModel.TzProd) {
	db := gorm.Db.Begin()
	var err error
	defer func() {
		if r := recover(); r != nil {
			db.Rollback()

		} else if err != nil {
			db.Rollback()
		} else {
			db.Commit()
		}
	}()
	db.Save(product)
	var dbSkuIds []uint64
	for _, sku := range dbProduct.SkuList {
		if sku.SkuID != nil {
			dbSkuIds = append(dbSkuIds, *sku.SkuID)
		}
	}
	// 将所有该商品的sku标记为已删除状态
	//update tz_sku set is_delete = 1 where prod_id = #{prodId}
	err = db.Model(&GormModel.TzSku{}).Where("prod_id =?", product.ProdID).Update("is_delete", 1).Error
	// 接口传入sku列表
	var skuList []GormModel.TzSku = product.SkuList
	if Util.SliceIsEmpty(skuList) {
		return
	}
	var insertSkuList []GormModel.TzSku
	for _, sku := range skuList {
		// 如果数据库中原有sku就更新，否者就插入
		if sku.SkuID == nil || Util.SliceContains(dbSkuIds, *sku.SkuID) {
			sku.ProdID = product.ProdID
			tmp := time.Now()
			sku.UpdateTime = &tmp
			sku.RecTime = &tmp
			IsDelete := 0
			sku.IsDelete = &IsDelete
			db.Save(&sku)
		} else {
			insertSkuList = append(insertSkuList, sku)
		}
	}
	// 批量插入sku
	if Util.SliceIsNotEmpty(insertSkuList) {
		//skuMapper.insertBatch(product.getProdId(), insertSkuList);
		for i := range insertSkuList {
			insertSkuList[i].ProdID = product.ProdID
		}
		result := db.Save(&insertSkuList)
		if result.Error != nil {
			err = result.Error
			log.Fatalf("failed to insert batch: %v", result.Error)
		}
	}
	//更新分组信息
	var tagList []int64 = product.TagList
	if Util.SliceIsNotEmpty(tagList) {
		//prodTagReferenceMapper.delete(new LambdaQueryWrapper<ProdTagReference>().eq(ProdTagReference::getProdId, product.getProdId()));
		db.Where("prod_id =?", product.ProdID).Delete(&GormModel.TzProdTagReference{})
		//prodTagReferenceMapper.insertBatch(dbProduct.getShopId(), product.getProdId(), tagList);
		// 准备批量插入的数据
		var insertList []GormModel.TzProdTagReference
		for _, tag := range tagList {
			insertList = append(insertList, GormModel.TzProdTagReference{
				ShopID:     1,
				ProdID:     int64(*product.ProdID),
				TagID:      tag,
				CreateTime: time.Now(),
			})
		}
		// 执行批量插入操作
		err := db.Create(&insertList).Error
		if err != nil {
			log.Fatalf("failed to insert batch: %v", err)
		}
	}
}
